package javango.forms.fields;

import java.util.Map;

import javango.forms.ValidationException;
import javango.forms.widgets.ChoicesWidget;
import javango.forms.widgets.SelectWidget;
import javango.forms.widgets.Widget;
import javango.forms.widgets.WidgetFactory;

import org.apache.commons.lang.StringUtils;

import com.google.inject.Inject;

public abstract class AbstractChoiceField<K,T> extends AbstractField<K> implements ChoiceField<K,T> {

	public final static String UNKNOWN_CHOICE_ERROR = "Select a valid choice. That choice is not one of the available choices.";
	public final static String NO_CHOICES_ERROR = "Select a valid choice. No choices are available.";
	
	@Inject
	public AbstractChoiceField(WidgetFactory widgetFactory) {
		super(widgetFactory);
		setWidget(SelectWidget.class);
	}

	protected Map<K,String> choices;
	
	public long getChoiceCount() {
		return choices == null ? 0 : choices.size();
	}

	public Map<K, String> getChoices() {
		return choices;
	}

	public ChoiceField<K, T> setChoices(Map<K,String> choices) {
		this.choices = choices;
//		Widget widget = getWidget();
		if (widget instanceof ChoicesWidget) {			
			((ChoicesWidget)widget).setChoices(choices);
			((ChoicesWidget)widget).setAddBlankEntry(isRequired() || isAllowNull());
		}
		return this;
	}
		
//	public T get(K key) {
//		if (choices == null) {
//			return null;
//		}
//		return choices.get(key);
//	}
	
	@Override
	public Field<K> setWidget(Widget widget) {
		if (widget instanceof ChoicesWidget) {
			((ChoicesWidget)widget).setChoices(this.getChoices());
			((ChoicesWidget)widget).setAddBlankEntry(isRequired() || isAllowNull());
		}

		return super.setWidget(widget);
	}

	@Override
	public K clean(String[] value, Map<String, String> errors) throws ValidationException {
		K myValue = super.clean(value, errors);
		if (myValue == null || (myValue instanceof String && StringUtils.isBlank((String)myValue))) {
			return myValue; // super should have flagged errors,  and cleaned correctly
		}
		Map<K,String> localChoices = getChoices();
		if (localChoices == null)   {
			errors.put(this.name, NO_CHOICES_ERROR);
		} else if (!localChoices.containsKey(myValue)) {
			errors.put(this.name, UNKNOWN_CHOICE_ERROR);
		}
		
		return myValue;
	}

}
